package edu.nf.relaxenjoy.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import edu.nf.relaxenjoy.common.constant.Constant;
import edu.nf.relaxenjoy.common.constant.platform.PlatformConstant;
import edu.nf.relaxenjoy.common.constant.platform.RabbitMqConstant;
import edu.nf.relaxenjoy.common.exception.CommonException;
import edu.nf.relaxenjoy.common.util.JsonUtils;
import edu.nf.relaxenjoy.common.util.RedisUtils;
import edu.nf.relaxenjoy.domain.dto.FollowDTO;
import edu.nf.relaxenjoy.domain.entity.Follow;
import edu.nf.relaxenjoy.domain.entity.Post;
import edu.nf.relaxenjoy.domain.entity.User;
import edu.nf.relaxenjoy.domain.vo.FollowVo;
import edu.nf.relaxenjoy.domain.vo.TrendVo;
import edu.nf.relaxenjoy.domain.vo.UserRecordVo;
import edu.nf.relaxenjoy.mapper.FollowMapper;
import edu.nf.relaxenjoy.mapper.PostMapper;
import edu.nf.relaxenjoy.mapper.UserMapper;
import edu.nf.relaxenjoy.service.FollowService;
import edu.nf.relaxenjoy.service.PlatformProducer;
import edu.nf.relaxenjoy.web.websocket.WebsocketServer;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zhu
 * @date 2024-12-19
 */
@Service
@RequiredArgsConstructor
public class FollowServiceImpl implements FollowService {

    private final FollowMapper followMapper;

    private final UserMapper userMapper;

    private final RedisUtils redisUtils;

    private final PlatformProducer platformProducer;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clearFollow(FollowDTO followDTO) {
        if (followDTO.getUid().equals(followDTO.getFid())) {
            return;
        }
        User currentUser = userMapper.getUserByUserId(followDTO.getUid());
        currentUser.setFollowCount(currentUser.getFollowCount() - 1);
        platformProducer.sendMessage(RabbitMqConstant.USER_STATE_EXCHANGE, RabbitMqConstant.USER_STATE_KEY, currentUser);


        User follower = userMapper.getUserByUserId(followDTO.getFid());
        follower.setFanCount(follower.getFanCount() - 1);
        platformProducer.sendMessage(RabbitMqConstant.USER_STATE_EXCHANGE, RabbitMqConstant.USER_STATE_KEY, follower);


        followMapper.remove(followDTO.getUid(), followDTO.getFid());
    }

    @Override
    public List<TrendVo> getAllFollowTrends(long page, long limit, String uid) {
        List<TrendVo> trendVos = followMapper.getAllFollowTrends(page, limit, uid);
        List<TrendVo> trendVoList = new ArrayList<>();
        for (TrendVo trendVo : trendVos) {
            trendVo.setImgsUrl(trendVo.getImgsUrl().replace("\\\"", "\""));
            trendVoList.add(trendVo);
        }
        return trendVoList;
    }

    @Override
    public PageInfo<FollowVo> getAllFriend(long page, long limit, String uid, Integer type) {
        PageInfo<FollowVo> followVoPage = new PageInfo<>();
        PageInfo<Follow> followPage;
        List<Long> uids;

        //0查找所有的粉丝
        if (type == 0) {
            followPage = new PageInfo<>(followMapper.getPageByFid(page, limit, Long.valueOf(uid)));
        } else {
            followPage = new PageInfo<>(followMapper.getPageByUid(page, limit, Long.valueOf(uid)));
        }

        List<Follow> followList = followPage.getList();
        long total = followPage.getTotal();

        if (type == 0) {
            uids = followList.stream().map(Follow::getUid).collect(Collectors.toList());
        } else {
            uids = followList.stream().map(Follow::getFid).collect(Collectors.toList());
        }

        List<User> userList = new ArrayList<>();
        HashMap<Long, User> userMap = new HashMap<>();
        if (uids != null && uids.size() > 0) {
            userList = userMapper.listByIds(uids);
            userList.forEach(item -> {
                userMap.put(item.getUserId(), item);
            });
        }

        //得到当前用户所有的关注
        List<Follow> followCurrentUserList = followMapper.getPageByUid(null, null, Long.valueOf(uid));
        List<Long> followIds = followCurrentUserList.stream().map(Follow::getFid).toList();

        FollowVo followVo;
        User user;
        List<FollowVo> followVoList = new ArrayList<>();
        for (Follow model : followList) {
            followVo = new FollowVo();
            //查找粉丝
            if (type == 0) {
                user = userMap.get(model.getUid());
            } else {
                user = userMap.get(model.getFid());
            }

            followVo.setIsfollow(followIds.contains(model.getUid()))
                    .setUid(user.getUserId())
                    .setUsername(user.getUsername())
                    .setAvatar(user.getAvatar())
                    .setFanCount(user.getFanCount())
                    .setUserId(user.getUserId())
                    .setTime(model.getCreateTime());
            followVoList.add(followVo);
        }

        followVoPage.setPageNum(followPage.getPageNum());
        followVoPage.setPageSize(followPage.getPageSize());
        followVoPage.setIsFirstPage(followPage.isIsFirstPage());
        followVoPage.setIsLastPage(followPage.isIsLastPage());
        followVoPage.setList(followVoList);
        followVoPage.setTotal(total);

        return followVoPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void followUser(FollowDTO followDTO) {
        if (followDTO.getUid().equals(followDTO.getFid())) {
            return;
        }

        Follow follow = new Follow();
        follow.setFid(followDTO.getFid());
        follow.setUid(followDTO.getUid());
        follow.setCreateTime(followDTO.getCreateTime());

        followMapper.insert(follow);

        User currentUser = userMapper.getUserByUserId(followDTO.getUid());
        currentUser.setFollowCount(currentUser.getFollowCount() + 1);
        platformProducer.sendMessage(RabbitMqConstant.USER_STATE_EXCHANGE, RabbitMqConstant.USER_STATE_KEY, currentUser);

        User followUser = userMapper.getUserByUserId(followDTO.getFid());
        followUser.setFanCount(followUser.getFanCount() + 1);
        platformProducer.sendMessage(RabbitMqConstant.USER_STATE_EXCHANGE, RabbitMqConstant.USER_STATE_KEY, followUser);

        //更改用户记录表
        String followerKey = PlatformConstant.USER_RECORD + followDTO.getFid();
        UserRecordVo follower;
        if (Boolean.TRUE.equals(redisUtils.hasKey(followerKey))) {
            follower = JsonUtils.parseObject(redisUtils.get(followerKey), UserRecordVo.class);
            follower.setAddFollowCount(follower.getAddFollowCount() + 1);
            redisUtils.set(followerKey, JSON.toJSONString(follower));

            try {
                WebsocketServer.sendMessageTo(JSON.toJSONString(follower), String.valueOf(followDTO.getFid()));
            } catch (Exception e) {
                throw new CommonException(Constant.MSG_ERROR);
            }
        }
    }

    @Override
    public boolean isFollow(String uid, String fid) {
        List<Follow> followList = followMapper.getPageByUid(null, null, Long.valueOf(uid));
        List<Long> fids = followList.stream().map(Follow::getFid).toList();
        return fids.contains(Long.valueOf(fid));
    }
}
